<script lang="ts" setup>
import { onMounted, reactive, ref, nextTick, onUnmounted } from 'vue';
const props = defineProps<{
    items?: {
        id: string,
        label: string,
        show: boolean,
        action: (obj?: any) => void
    }[]
    octmData?: any
}>()
const contextMenuDivRef = ref()
const contextMenuRef = ref()
const show = ref(false);
const pos = reactive({ x: 0, y: 0 });
let eventObj: any = null
// 事件总线实现
const bus = {
    emit(event: string) {
        document.dispatchEvent(new CustomEvent(event));
    },
    on(event: any, callback: (this: Document, ev: any) => any) {
        document.addEventListener(event, callback);
    },
    off(event: any, callback: (this: Document, ev: any) => any) {
        document.removeEventListener(event, callback);
    }
};

// 关闭所有菜单
const closeAllMenus = () => {
    bus.emit('close-all-menus');
};

const refreshItem = {
    id: 'refresh',
    label: '刷新',
    show: true,
    action: () => {
        location.reload()
    }
}
function operContextMenu(event: any) {
    event.stopPropagation();
    event.preventDefault();
    // 关闭其他菜单
    closeAllMenus();
    show.value = true
    nextTick(() => {
        let x = event.clientX
        let y = event.clientY
        const { clientWidth, clientHeight } = document.body
        if (clientWidth - event.clientX < 100) {
            x -= 100
        }
        if (clientHeight - event.clientY < contextMenuRef.value.clientHeight) {
            y -= contextMenuRef.value.clientHeight
        }
        pos.x = x
        pos.y = y
        eventObj = event
    })
}
// 菜单项点击事件
function operAction(item: any) {
    item.action({ event: eventObj, octmData: props.octmData })
    close()
}

function close() {
    show.value = false
}
onMounted(() => {
    bus.on('close-all-menus', () => {
        close()
    });
    // 全局点击事件 - 点击菜单外部区域关闭菜单
    document.addEventListener('click', closeAllMenus);

    window.addEventListener('resize', closeAllMenus);
})
onUnmounted(() => {
    bus.off('close-all-menus', () => {
        close()
    });
    document.removeEventListener('click', () => {})
    window.removeEventListener('resize', () => {});
})
</script>
<template>
    <div ref="contextMenuDivRef" @contextmenu="operContextMenu" class="contextMenuDiv">
        <slot></slot>
        <div ref="contextMenuRef" v-if="show" class="contextMenu" :style="{ top: pos.y + 'px', left: pos.x + 'px' }">
            <div v-for="item in [...(items || []), refreshItem]" :key="item.id" v-show="item.show" class="item"
                @click.stop="operAction(item)">{{ item.label }}</div>
        </div>
    </div>
</template>
<style lang="scss" scoped>
.contextMenuDiv {
    position: relative;

    .contextMenu {
        position: fixed;
        top: 40%;
        left: 50%;
        width: 100px;
        z-index: 2025;
        background-color: #fff;
        padding: 3px;
        box-shadow: var(--el-box-shadow-light);
        border-radius: 6px;
        color: #000;

        .item {
            cursor: default;
            text-align: center;
            padding: 3px 0;

            &:hover {
                background-color: #e6e6e6;
            }
        }
    }
}
</style>